﻿using EBA.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml.Serialization;

namespace EBA.Logging
{
    /// <summary>
    /// Write the diagnostic message into a text file.
    /// </summary>
    // [Export("FlatFileLogger", typeof(ILogger))]
    class XmlFileLogger : ILogger
    {
        static volatile object SycnRoot = new object();


        internal XmlFileLogger(string logFile, string name = null)
        {
            this.LogFile = logFile;
            this.Name = name;
        }

        public string Name
        {
            get;
            set;
        }

        string LogFile { get; set; }

        /// <summary>
        /// Writes the diagnostic message at the specified level.
        /// </summary>
        /// <param name="message">log message</param>
        /// <param name="level">log level</param>
        /// <param name="name"></param>
        public void Log(string message, LogLevel level = LogLevel.Info, string name = null)
        {
            var log = new XElementLog
            {
                Id = Guid.NewGuid().ToString("N"),
                Level = level,
                AddedTime = DateTime.Now,
                Message = message,
                Name = name
            };
            var sb = new StringBuilder(XmlFileLogSerializer.Serialize(log));
            sb.AppendLine();
            WriteToFile(sb.ToString());
        }


        public void Log<TEntity>(string message, TEntity entity, LogLevel level = LogLevel.Info, string name = null)
        {
            var log = new XElementLog
            {
                Id = Guid.NewGuid().ToString("N"),
                Level = level,
                AddedTime = DateTime.Now,
                Message = message,
                Name = name,
                Data = entity
            };
            var sb = new StringBuilder(XmlFileLogSerializer.Serialize<TEntity>(log));
            sb.AppendLine();
            WriteToFile(sb.ToString());
        }

        private void WriteToFile(string str)
        {
            lock (SycnRoot)
            {
                using (var writer = File.Open(this.LogFile, FileMode.Append))
                {
                    var buffer = UTF8Encoding.UTF8.GetBytes(str);
                    writer.Write(buffer, 0, buffer.Length);
                }
            }
        }
    }
}
